/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu 
 * date:2016年4月4日
 *
 */
package com.acooly.module.openapi.client.provider.bosc.marshall;

import com.acooly.core.utils.Strings;
import com.acooly.core.utils.validate.Validators;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.message.ApiMessage;
import com.acooly.module.openapi.client.api.util.Jsons;
import com.acooly.module.openapi.client.provider.bosc.BoscConstants;
import com.acooly.module.openapi.client.provider.bosc.OpenAPIClientBoscProperties;
import com.acooly.module.openapi.client.provider.bosc.domain.ApiMsgInfo;
import com.acooly.module.openapi.client.provider.bosc.domain.BoscMessage;
import com.acooly.module.openapi.client.provider.bosc.domain.BoscRequest;
import com.acooly.module.safety.Safes;
import com.acooly.module.safety.signature.SignTypeEnum;
import com.acooly.module.safety.support.KeyPair;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Map;

/**
 * @author zhangpu
 */
@Slf4j
public class BoscMarshallSupport {

    protected static final char SPLIT_CHAR = '|';

    @Autowired
    protected OpenAPIClientBoscProperties openAPIClientBoscProperties;


    private KeyPair keyPair;

    protected OpenAPIClientBoscProperties getProperties() {
        return openAPIClientBoscProperties;
    }


    protected Map<String, String> doMarshall(BoscRequest source) {
        doVerifyParam(source);
        String reqData = Jsons.toJson(source);
        source.setSign(doSign(reqData));
        Map<String, String> data = Maps.newHashMap();
        data.put(BoscConstants.SERVICE_NAME, getServiceName(source));
        if (Strings.isBlank(source.getPartner())) {
            source.setPartner(getProperties().getPlatformNo());
        }
        data.put(BoscConstants.PLATFORM_NO, source.getPartner());
        data.put(BoscConstants.KEY_SERIAL, source.getSerialkey());
        if (Strings.isNotBlank(source.getUserDevice())) {
            data.put(BoscConstants.USER_DEVICE, source.getUserDevice());
        }
        data.put(BoscConstants.SIGN, source.getSign());
        data.put(BoscConstants.REQ_DATA, reqData);
        log.info("请求报文: {}", data);
        return data;
    }


    protected void doVerifyParam(BoscMessage source) {
        try {
            source.doCheck();
            Validators.assertJSR303(source);
        } catch (Exception e) {
            throw new ApiClientException(e.getMessage());
        }
    }


    protected String doSign(String waitForSign) {
        return Safes.getSigner(SignTypeEnum.Rsa.name()).sign(waitForSign, getKeyPair());
    }


    protected ApiMsgInfo getApiMsgInfo(ApiMessage apiMessage) {
        return apiMessage.getClass().getAnnotation(ApiMsgInfo.class);
    }

    protected String getServiceName(ApiMessage apiMessage) {
        if (Strings.isNotBlank(apiMessage.getService())) {
            return apiMessage.getService();
        }

        ApiMsgInfo apiMsgInfo = getApiMsgInfo(apiMessage);
        if (apiMsgInfo != null && apiMsgInfo.service() != null) {
            return apiMsgInfo.service().code();
        }
        throw new RuntimeException("请求报文的service为空");
    }

    protected KeyPair getKeyPair() {
        if (keyPair == null) {
            synchronized (this) {
                if (keyPair == null) {
                    keyPair = new KeyPair(openAPIClientBoscProperties.getPublicKey(),
                            openAPIClientBoscProperties.getPrivateKey());
                    keyPair.loadKeys();
                }
            }
        }
        return keyPair;
    }

}
